//! 标准库类型 (Standard Library Types) ——智能指针
//!
//! Rust 标准库提供了许多有用的类型，这些类型在日常编程中非常常见。
//! 这些类型包括 `Box`、`Rc`、`Arc`、`Cell`、`RefCell` 等。

use std::cell::Cell;
use std::collections::HashMap;
use std::rc::Rc;
use std::sync::{Arc, Mutex};

/// 1. `Box<T>` - 堆分配值的智能指针
///
/// `Box<T>` 允许你在堆上分配值而不是栈上，但仍提供栈上值的语义。
pub fn box_example() {
    println!("=== Box<T> 示例 ===");

    // 在堆上分配一个整数值
    let boxed_int = Box::new(5);
    println!("boxed_int 的值: {}", boxed_int);

    // 使用 Box 创建递归类型
    #[derive(Debug)]
    enum List {
        Cons(i32, Box<List>),
        Nil,
    }

    use List::*;

    let list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));
    println!("列表: {:?}", list);
}

/// 2. `Rc<T>` - 引用计数智能指针
///
/// `Rc<T>`（Reference Counted）允许多个所有者拥有同一个数据。
/// 它只能用于单线程场景。
pub fn rc_example() {
    println!("\n=== Rc<T> 示例 ===");

    // 创建一个 Rc 实例
    let rc1 = Rc::new(String::from("Rc 示例"));
    println!("引用计数: {}", Rc::strong_count(&rc1));

    // 创建另一个指向相同数据的 Rc
    let rc2 = Rc::clone(&rc1);
    println!("引用计数: {}", Rc::strong_count(&rc1));

    println!("rc1: {}, rc2: {}", rc1, rc2);

    // 当 Rc 离开作用域时，引用计数会减少
    drop(rc2);
    println!("引用计数: {}", Rc::strong_count(&rc1));
}

/// 3. `Arc<T>` - 原子引用计数智能指针
///
/// `Arc<T>`（Atomically Reference Counted）是 `Rc<T>` 的线程安全版本。
pub fn arc_example() {
    println!("\n=== Arc<T> 示例 ===");

    let arc = Arc::new(String::from("Arc 示例"));
    println!("Arc 值: {}", arc);

    let arc1 = Arc::clone(&arc);
    let arc2 = Arc::clone(&arc);

    println!("克隆后的 Arc: {}, {}", arc1, arc2);
}

/// 4. `Cell<T>` 和 `RefCell<T>` - 内部可变性
///
/// `Cell<T>` 和 `RefCell<T>` 提供了"内部可变性"模式。
/// `Cell<T>` 适用于 Copy 类型，`RefCell<T>` 适用于其他类型。
pub fn cell_refcell_example() {
    println!("\n=== Cell<T> 和 RefCell<T> 示例 ===");

    // Cell 示例 - 适用于 Copy 类型
    let cell = Cell::new(5);
    println!("Cell 初始值: {}", cell.get());

    cell.set(10);
    println!("Cell 修改后: {}", cell.get());

    // RefCell 示例 - 运行时借用检查
    let ref_cell = std::cell::RefCell::new(String::from("Hello"));
    println!("RefCell 初始值: {}", ref_cell.borrow());

    // 修改 RefCell 中的值
    {
        let mut borrowed = ref_cell.borrow_mut();
        borrowed.push_str(", World!");
    }

    println!("RefCell 修改后: {}", ref_cell.borrow());
}

/// 5. `Mutex<T>` - 互斥锁
///
/// `Mutex<T>` 提供了线程间共享可变数据的机制。
pub fn mutex_example() {
    println!("\n=== Mutex<T> 示例 ===");

    let mutex = Mutex::new(HashMap::new());

    // 获取锁并修改数据
    {
        let mut map = mutex.lock().unwrap();
        map.insert("key1", "value1");
        map.insert("key2", "value2");
    }

    // 读取数据
    {
        let map = mutex.lock().unwrap();
        println!("Mutex 中的值: {:?}", *map);
    }
}

/// 6. `Option<T>` 和 `Result<T, E>`
///
/// `Option<T>` 表示一个值可能存在也可能不存在。
/// `Result<T, E>` 表示一个操作可能成功（返回 T）或失败（返回 E）。
pub fn option_result_example() {
    println!("\n=== Option<T> 和 Result<T, E> 示例 ===");

    let some_value: Option<i32> = Some(42);
    let none_value: Option<i32> = None;

    println!("Some 值: {:?}", some_value);
    println!("None 值: {:?}", none_value);

    let ok_result: Result<i32, &str> = Ok(42);
    let err_result: Result<i32, &str> = Err("出错了");

    println!("Ok 结果: {:?}", ok_result);
    println!("Err 结果: {:?}", err_result);
}

/// 主演示函数
pub fn demonstrate_std_types() {
    box_example();
    rc_example();
    arc_example();
    cell_refcell_example();
    mutex_example();
    option_result_example();
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_box() {
        let boxed_int = Box::new(5);
        assert_eq!(*boxed_int, 5);
    }

    #[test]
    fn test_rc() {
        let rc1 = Rc::new(String::from("test"));
        let rc2 = Rc::clone(&rc1);

        assert_eq!(Rc::strong_count(&rc1), 2);
        assert_eq!(*rc1, "test");
        assert_eq!(*rc2, "test");
    }

    #[test]
    fn test_cell() {
        let cell = Cell::new(5);
        assert_eq!(cell.get(), 5);

        cell.set(10);
        assert_eq!(cell.get(), 10);
    }

    #[test]
    fn test_refcell() {
        let ref_cell = std::cell::RefCell::new(String::from("Hello"));
        assert_eq!(*ref_cell.borrow(), "Hello");

        {
            let mut borrowed = ref_cell.borrow_mut();
            borrowed.push_str(", World!");
        }

        assert_eq!(*ref_cell.borrow(), "Hello, World!");
    }
}
